package com.gopay.common.cipher.algorithm.baseAlgorithm;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

/**
 * 
 * @ClassName: Cipher3DES 
 * @Description: 与Security3DES类的功能基本一致，敏感信息处理中单独使用一份，方便后续的修改，且不影响之前的功能 
 * @author zyt 
 * @date 2016年12月1日 上午10:04:34
 */
public class Cipher3DES {

    private static ThreadLocal<Base64> base64Holder = new ThreadLocal<Base64>(){
        @Override
        protected Base64 initialValue() {
            return new Base64();
        }
    };
    
    private static final String KEY_TYPE = "DESede"; // 定义 密钥类型
    
    //定义加密算法，DESede，工作模式：ECB，填充方式：PKCS5Padding
    private static final String ALGORITHM = "DESede/ECB/PKCS5Padding";	

    // keybyte为加密密钥，长度为24字节
    // src为被加密的数据缓冲区（源）
    public static byte[] encrypt(byte[] keybyte, byte[] src) throws Exception {
        try {
            // 生成密钥
            SecretKey deskey = new SecretKeySpec(keybyte, KEY_TYPE);

            // 加密
            Cipher c1 = Cipher.getInstance(ALGORITHM);
            c1.init(Cipher.ENCRYPT_MODE, deskey);
            return c1.doFinal(src);
        } catch (java.security.NoSuchAlgorithmException e1) {
        	throw new Exception("Cipher3DES-encrypt() error:" +
					"未知的解密算法");
        } catch (javax.crypto.NoSuchPaddingException e2) {
        	throw new Exception("Cipher3DES-encrypt() error:" +
					"未知的填充方式");
        } catch (java.lang.Exception e3) {
        	throw new Exception("Cipher3DES-encrypt() error:" ,
					e3);
        }
        //return null;
    }

    // keybyte为加密密钥，长度为24字节
    // src为加密后的缓冲区
    public static byte[] decrypt(byte[] keybyte, byte[] src) throws Exception {
        try {
            // 生成密钥
            SecretKey deskey = new SecretKeySpec(keybyte, KEY_TYPE);
            // 解密
            Cipher c1 = Cipher.getInstance(ALGORITHM);
            c1.init(Cipher.DECRYPT_MODE, deskey);
            return c1.doFinal(src);
        } catch (java.security.NoSuchAlgorithmException e1) {
        	throw new Exception("Cipher3DES-decrypt() error:" +
					"未知的解密算法");
        } catch (javax.crypto.NoSuchPaddingException e2) {
        	throw new Exception("Cipher3DES-decrypt() error:" +
					"未知的填充方式");
        } catch (java.lang.Exception e3) {
        	throw new Exception("Cipher3DES-decrypt() error:" ,
					e3);
        }
        //return null;
    }
    
    public static byte[] decryptBase64(byte[] keybyte, byte[] src) throws Exception {
        
        if (src != null) {
            src = base64Holder.get().decode(src);
        }
        
        return decrypt(keybyte, src);
    }
    
    public static byte[] encryptBase64(byte[] keybyte, byte[] src) throws Exception {
        byte[] ret =  encrypt(keybyte, src);
        
        if (ret != null) {
            ret = base64Holder.get().encode(ret);
        }
        return ret;
    }


    public static String byteArr2HexStr(byte[] bytea) throws Exception {  
        String sHex = "";  
        int iUnsigned = 0;  
        StringBuffer sbHex = new StringBuffer();  
        for (int i = 0; i < bytea.length; i++) {  
            iUnsigned = bytea[i];  
            if (iUnsigned < 0) {  
                iUnsigned += 256;  
            }  
            if (iUnsigned < 16) {  
                sbHex.append("0");  
            }  
            sbHex.append(Integer.toString(iUnsigned, 16));  
        }  
        sHex = sbHex.toString();  
        return sHex;  
    }  
  
    private static byte[] hexStr2ByteArr(String strIn) throws Exception {  
        byte[] arrB = strIn.getBytes();  
        int iLen = arrB.length;  
  
        // 两个字符表示一个字节，所以字节数组长度是字符串长度除以2  
        byte[] arrOut = new byte[iLen / 2];  
        for (int i = 0; i < iLen; i = i + 2) {  
            String strTmp = new String(arrB, i, 2);  
            arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);  
        }  
        return arrOut;  
    }  

    public static void main(String[] args) throws Exception {

        byte[] keyByte = "password12345678password".getBytes();
        byte[] srcByte = "passwordpassword".getBytes();
        //byte[] srcByte = "赵亚亭".getBytes();
        byte[] encoded = encrypt(keyByte, srcByte);
        System.out.println(new String(byteArr2HexStr(encoded)));
    	System.out.println(new String(byteArr2HexStr("password1245678mytest".getBytes())));
    	/*System.out.println(new String(
    			decryptBase64(Arrays.copyOf("gopay".getBytes(), 24),"BCk6fbCrVV40IFokMvCWML1pVAVja4Dj".getBytes())));
    	*/
    	System.out.println();
    	/*Cipher3DES s = new Cipher3DES();
    	String sHexPlainText = "passwordpassword"; 
    	byte[] byteaCryptograph = encrypt(Arrays.copyOf("91sj!XwuGMcuEl^J$#l6AhAW".getBytes(), 24),sHexPlainText.getBytes());
    	System.out.println("密文长度:" + byteaCryptograph.length);
    	System.out.println("密文内容:" + byteArr2HexStr(byteaCryptograph));
    	byte[] doubleByte = Hex.decode("C83C87A75B3A997B0A078A97BAA0300B70B1BC6F1E5371D6".getBytes());
    	System.out.println();
    	
    	//byte[] keyByte = "91sj!XwuGMcuEl^J$#l6AhAW".getBytes();
    	System.out.println(new String(byteArr2HexStr("abcdefg123456".getBytes())));
    	byte[] keyByte = hexStr2ByteArr("C83C87A75B3A997B0A078A97BAA0300B70B1BC6F1E5371D6");
        byte[] srcByte = "passwordpassword".getBytes();
        //byte[] srcByte = "赵亚亭".getBytes();
        byte[] encoded = encrypt(keyByte, srcByte);
        byte[] encodedBaseEn = base64Holder.get().encode(encoded);
        byte[] baseEn = s.encryptBase64(keyByte, srcByte);
        byte[] baseEnDe = base64Holder.get().decode(baseEn);
        System.out.println("原文byte:" + byteArr2HexStr(srcByte));
        System.out.println(encoded.length);
        System.out.println("密文16进制：" + byteArr2HexStr(encoded));
        System.out.println("密文base64字符串：" + new String(encodedBaseEn));
        System.out.println(baseEn.length);
        System.out.println(byteArr2HexStr(baseEn));
        System.out.println("base64:" + new String(baseEn));
        System.out.println(baseEnDe.length);
        System.out.println(byteArr2HexStr(baseEnDe));
        
        byte[] decoded = decrypt(keyByte, encoded);
        System.out.println(decoded.length);
        System.out.println(new String(decoded));*/
        /*for(byte b : decoded){
        	System.out.print((char)b);
        }*/
        //System.out.println(byteArr2HexStr(decoded));
    	
        // 添加新安全算法,如果用JCE就要把它添加进去
        // Security.addProvider(new com.sun.crypto.provider.SunJCE());

       /* final byte[] keyBytes = Arrays.copyOf("91sj!XwuGMcuEl^J$#l6AhAW".getBytes(), 24); // 24字节的密钥
        String szSrc = "1234567890";

        System.out.println("加密前的字符串:" + szSrc);

        byte[] keyByte = Hex.encode("91sj!XwuGMcuEl^J$#l6AhAW".getBytes());
        byte[] srcByte = Hex.encode("passwordpassword".getBytes());
        System.out.println(srcByte.length);
        System.out.println("" + new String(srcByte));
        //byte[] encoded = encryptBase64(keyBytes, srcByte);
        byte[] encoded = encrypt(keyBytes, srcByte);
        System.out.println(byte2hex(encoded));
        System.out.println(encoded.length);
        String res = new String(encoded,"utf-8");
        System.out.println("encrypt加密后的字符串:" +  res);
        System.out.println("encrypt加密后的byte2hex字符串:" +  byteArr2HexStr(encoded));*/
        /* byte[] resByte = Hex.decode(encoded);
        for(byte b : resByte){
        	System.out.print((char)b);
        }
        byte[] srcBytes = encryptBase64(keyBytes, srcByte);
        System.out.println("encryptBase64加密后的字符串:" + (new String(srcBytes)));
        System.out.println("encryptBase64加密后的byte2hex字符串:" + byte2hex(srcBytes));
        byte[] resByte = Hex.decode(srcBytes);
        for(byte b : resByte){
        	System.out.print((char)b);
        }*/
    }

}